using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace MKDS_Course_Editor.GCN.Sound
{
    class BAAD
    {
        public enum FileType
        {
            bst,
            bstn,
            ws,
            bnk,
            bsft,
            bsc,
            bms,
            baac,
            bfca
        }
        public class BaaContentFile
        {
            public FileType Filetype;
            public byte[] Content;
            public BaaContentFile(FileType t, byte[] b)
            {
                Filetype = t;
                Content = b;
            }
        }
        public static List<BaaContentFile> ReadBAA(string file)
        {
            List<BaaContentFile> ar = new List<BaaContentFile>();
            EndianBinaryReader er = new EndianBinaryReader(File.OpenRead(file), Endianness.BigEndian);
            long lastoffset = 0;
            long baseoffset = 0;
            while (er.BaseStream.Position != er.BaseStream.Length - 4)
            {
                try
                {
                    switch (er.ReadString(Encoding.ASCII, 4))
                    {
                        case "AA_<":
                            baseoffset = er.BaseStream.Position - 4;
                            break;
                        case "bst ":
                            {
                                int offset = er.ReadInt32();
                                int size = er.ReadInt32() - offset;
                                offset += (int)baseoffset;
                                long curoffset = er.BaseStream.Position;
                                er.BaseStream.Position = offset;
                                ar.Add(new BaaContentFile(FileType.bst, er.ReadBytes(size)));
                                if (offset + size > lastoffset) lastoffset = offset + size;
                                er.BaseStream.Position = curoffset;
                                break;
                            }
                        case "bstn":
                            {
                                int offset = er.ReadInt32();
                                int size = er.ReadInt32() - offset;
                                offset += (int)baseoffset;
                                long curoffset = er.BaseStream.Position;
                                er.BaseStream.Position = offset;
                                ar.Add(new BaaContentFile(FileType.bstn, er.ReadBytes(size)));
                                if (offset + size > lastoffset) lastoffset = offset + size;
                                er.BaseStream.Position = curoffset;
                                break;
                            }
                        case "ws  ":
                            {
                                int id = er.ReadInt32();
                                int offset = er.ReadInt32();
                                offset += (int)baseoffset;
                                int unknown = er.ReadInt32();
                                long curoffset = er.BaseStream.Position;
                                er.BaseStream.Position = offset + 4;
                                int size = er.ReadInt32();
                                er.BaseStream.Position = offset;
                                ar.Add(new BaaContentFile(FileType.ws, er.ReadBytes(size)));
                                if (offset + size > lastoffset) lastoffset = offset + size;
                                er.BaseStream.Position = curoffset;
                                break;
                            }
                        case "bnk ":
                            {
                                int id = er.ReadInt32();
                                int offset = er.ReadInt32();
                                offset += (int)baseoffset;
                                long curoffset = er.BaseStream.Position;
                                er.BaseStream.Position = offset + 4;
                                int size = er.ReadInt32();
                                er.BaseStream.Position = offset;
                                ar.Add(new BaaContentFile(FileType.bnk, er.ReadBytes(size)));
                                if (offset + size > lastoffset) lastoffset = offset + size;
                                er.BaseStream.Position = curoffset;
                                break;
                            }
                        case "bfca":
                            {
                                int offset = er.ReadInt32();
                                offset += (int)baseoffset;
                                long curoffset = er.BaseStream.Position;
                                er.BaseStream.Position = offset + 4;
                                int size = er.ReadInt32();
                                er.BaseStream.Position = offset;
                                ar.Add(new BaaContentFile(FileType.bfca, er.ReadBytes(size)));
                                if (offset + size > lastoffset) lastoffset = offset + size;
                                er.BaseStream.Position = curoffset;
                                break;
                            }
                        case "bsft":
                            {
                                int offset = er.ReadInt32();
                                offset += (int)baseoffset;
                                long curoffset = er.BaseStream.Position;
                                er.BaseStream.Position = offset + 4;
                                int size = er.ReadInt32();
                                er.BaseStream.Position = offset;
                                ar.Add(new BaaContentFile(FileType.bsft, er.ReadBytes(size)));
                                if (offset + size > lastoffset) lastoffset = offset + size;
                                er.BaseStream.Position = curoffset;
                                break;
                            }
                        case "bsc ":
                            {
                                int offset = er.ReadInt32();
                                int size = er.ReadInt32() - offset;
                                offset += (int)baseoffset;
                                long curoffset = er.BaseStream.Position;
                                er.BaseStream.Position = offset;
                                ar.Add(new BaaContentFile(FileType.bsc, er.ReadBytes(size)));
                                if (offset + size > lastoffset) lastoffset = offset + size;
                                er.BaseStream.Position = curoffset;
                                break;
                            }
                        case "bms ":
                            {
                                int id = er.ReadInt32();
                                int offset = er.ReadInt32();
                                int size = er.ReadInt32() - offset;
                                offset += (int)baseoffset;
                                long curoffset = er.BaseStream.Position;
                                er.BaseStream.Position = offset;
                                ar.Add(new BaaContentFile(FileType.bms, er.ReadBytes(size)));
                                if (offset + size > lastoffset) lastoffset = offset + size;
                                er.BaseStream.Position = curoffset;
                                break;
                            }
                        case "baac":
                            {
                                int offset = er.ReadInt32();
                                offset += (int)baseoffset;
                                long curoffset = er.BaseStream.Position;
                                er.BaseStream.Position = offset + 4;
                                int size = er.ReadInt32();
                                er.BaseStream.Position = offset;
                                ar.Add(new BaaContentFile(FileType.baac, er.ReadBytes(size)));
                                if (offset + size > lastoffset) lastoffset = offset + size;
                                er.BaseStream.Position = curoffset;
                                break;
                            }
                        case ">_AA":
                            while (er.BaseStream.Length - er.BaseStream.Position != 4)
                            {
                                if (er.ReadString(Encoding.ASCII, 4) == "AA_<")
                                {
                                    er.BaseStream.Position -= 4;
                                    break;
                                }
                            }
                            break;

                        default:
                            break;
                    }
                }
                catch
                {

                }
            }
            er.Close();
            return ar;
        }
    }
}
